﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

namespace IPC.WinForm.WG
{
    public class ConfigEquip : BaseEquip
    {
        #region 扩展字段

        private bool _isEnableGroup = false;
        private string _groupRange = String.Empty;

        #endregion

        #region 扩展属性

        /// <summary>
        /// 是否启用设备群组
        /// </summary>
        public bool IsEnableGroup
        {
            get { return _isEnableGroup; }
            set { _isEnableGroup = value; }
        }
        /// <summary>
        /// 设备群组范围
        /// </summary>
        public string GroupRange
        {
            get { return _groupRange; }
            set { _groupRange = value; }
        }

        #endregion

        #region 属性定义
        public string IP { get; set; }

        public string Rack { get; set; }

        public string Slot { get; set; }
        /// <summary>
        /// 设备名称
        /// </summary>
        [Caption("")]
        public string Name { get; set; }
        /// <summary>
        /// 项目名称
        /// </summary>
        public string Project { get; set; }
        /// <summary>
        /// 设备主信息
        /// </summary>
        public Main Main { get; set; }
        /// <summary>
        /// 设备数据块信息
        /// </summary>
        public Dictionary<string, Group> Group { get; set; }
        /// <summary>
        /// 设备状态
        /// </summary>
        public bool State { get; protected set; }
        /// <summary>
        /// 是否最小读取频率的设备
        /// </summary>
        public bool IsMinReadHZ { get; set; }

        #endregion

        public Dictionary<string, BaseEquip> ReadBaseEquip(bool isConfigEquip,string configFile)
        {
            Dictionary<string, BaseEquip> Result = new Dictionary<string, BaseEquip>();
            if (!File.Exists(configFile))
            {
                return Result;
            }
            XmlDocument xmlDocument = new XmlDocument();
            xmlDocument.Load(configFile);
            foreach (XmlNode factoryNode in xmlDocument)
            {
                //跳过注释
                if (factoryNode.NodeType == XmlNodeType.Comment)
                {
                    continue;
                }
                if (factoryNode.Name == "EquipFactory")
                {
                    foreach (XmlNode EquipNode in factoryNode.ChildNodes)
                    {
                        //跳过注释
                        if (EquipNode.NodeType == XmlNodeType.Comment)
                        {
                            continue;
                        }
                        string? equipNameStr = EquipNode?.Attributes?["name"]?.Value.ToString();
                        ParseEquip(equipNameStr, isConfigEquip, Result, EquipNode);
                    }
                }
            }
            return Result;
        }
        /// <summary>
        /// 从Xml配置文件中解析设备
        /// </summary>
        /// <param name="equipName"></param>
        /// <param name="isConfigEquip"></param>
        /// <param name="Result"></param>
        /// <param name="EquipNode"></param>
        private void ParseEquip(string? equipName, bool isConfigEquip, Dictionary<string, BaseEquip> Result, XmlNode? EquipNode)
        {
            ConfigEquip equip = new ConfigEquip();
            equip.Name = equipName;
            equip.Project = EquipNode.Attributes["project"].Value.ToString();
            equip.Main = new Main();
            equip.Group = new Dictionary<string, Group>();

            #region 郑立兵于2014-01-19扩展，用于解析设备的群组配置

            if (null == EquipNode.Attributes["isEnableGroup"] || String.IsNullOrEmpty(EquipNode.Attributes["isEnableGroup"].Value))
            {
                equip.IsEnableGroup = false;
                equip.GroupRange = String.Empty;
            }
            else
            {
                string strIsEnableGroup = EquipNode.Attributes["isEnableGroup"].Value.Trim();
                bool isEnableGroup = false;
                bool.TryParse(strIsEnableGroup, out isEnableGroup);
                equip.IsEnableGroup = isEnableGroup;
                if (null == EquipNode.Attributes["groupRange"])
                {
                    equip.GroupRange = String.Empty;
                }
                else
                {
                    string strGroupRange = EquipNode.Attributes["groupRange"].Value.Trim();
                    if (!String.IsNullOrEmpty(strGroupRange))
                    {
                        equip.GroupRange = strGroupRange;
                    }
                }
            }

            #endregion

            #region Main
            string ss = string.Empty;
            equip.Main.Equip = equip;
            GetFirstNodeValue(EquipNode, ".//Main//Brand[@value]", "value", true, out ss);
            equip.Main.Brand = ss;
            GetFirstNodeValue(EquipNode, ".//Main//Model[@value]", "value", true, out ss);
            equip.Main.Model = ss;
            GetFirstNodeValue(EquipNode, ".//Main//ReadHz[@value]", "value", true, out ss);
            int strToInt = 0;
            if (int.TryParse(ss, out strToInt))
            {
                equip.Main.ReadHz = strToInt;
            }
            GetFirstNodeValue(EquipNode, ".//Main//UnitLen[@value]", "value", true, out ss);
            strToInt = 0;
            if (int.TryParse(ss, out strToInt))
            {
                equip.Main.UnitLen = strToInt;
            }
            GetFirstNodeValue(EquipNode, ".//Main//Connection[@mode]", "mode", true, out ss);
            equip.Main.ConnType = "Net";

            GetFirstNodeValue(EquipNode, ".//Main//Connection//IP[@value]", "value", true, out ss);
            equip.IP = ss;

            GetFirstNodeValue(EquipNode, ".//Main//Connection//Rack[@value]", "value", true, out ss);
            equip.Rack = ss;

            GetFirstNodeValue(EquipNode, ".//Main//Connection//Slot[@value]", "value", true, out ss);
            equip.Slot = ss;
            #endregion

            #region Group
            XmlNodeList groupNodes = EquipNode.SelectNodes(".//Group")[0].ChildNodes;
            foreach (XmlNode groupNode in groupNodes)
            {
                #region 过滤注释

                if (groupNode.NodeType == XmlNodeType.Comment)
                {
                    continue;
                }

                #endregion

                Group group = new Group();
                group.Equip = equip;
                GetNodeAttributeValue(groupNode, "name", true, out ss);
                group.Name = ss;
                GetNodeAttributeValue(groupNode, "runname", true, out ss);
                group.RunName = ss;
                GetNodeAttributeValue(groupNode, "remark", false, out ss);
                group.Remark = ss;
                GetNodeAttributeValue(groupNode, "datatype", false, out ss);
                group.DataType = ss;
                GetNodeAttributeValue(groupNode, "start", true, out ss);
                group.Start = Convert.ToInt32(ss);
                GetNodeAttributeValue(groupNode, "block", true, out ss);
                group.Block = ss;
                GetNodeAttributeValue(groupNode, "len", true, out ss);
                group.Len = Convert.ToInt32(ss);
                GetNodeAttributeValue(groupNode, "isautoread", false, out ss);
                group.IsAutoRead = true;
                if (ss.ToLower() == "false" ||
                    ss == "0")
                {
                    group.IsAutoRead = false;
                }
                GetNodeAttributeValue(groupNode, "access", false, out ss);
                group.Access = System.IO.FileAccess.ReadWrite;
                if (string.IsNullOrEmpty(ss))
                {
                    ss = "ReadWrite";
                }
                if (ss.Equals("Read", StringComparison.CurrentCultureIgnoreCase))
                {
                    group.Access = System.IO.FileAccess.Read;
                }
                if (ss.Equals("Write", StringComparison.CurrentCultureIgnoreCase))
                {
                    group.Access = System.IO.FileAccess.Write;
                }
                if (equip.Group.ContainsKey(group.Name))
                {
                }
                else
                {
                    equip.Group.Add(group.Name, group);
                }

                #region Data

                XmlNodeList dataLisst = groupNode.SelectNodes(".//Data");
                if (dataLisst == null || dataLisst.Count == 0)
                {
                    continue;
                }
                //XmlNodeList dataNodes = groupNode.SelectNodes(".//Data")[0].ChildNodes;
                XmlNodeList dataNodes = dataLisst[0].ChildNodes;
                foreach (XmlNode node in dataNodes)
                {
                    #region 过滤注释

                    if (node.NodeType == XmlNodeType.Comment)
                    {
                        continue;
                    }

                    #endregion

                    Data data = new Data();
                    if(group.Data == null)
                    {
                        group.Data = new Dictionary<string, Data>();
                    }
                    data.Group = group;
                    GetNodeAttributeValue(node, "name", true, out ss);
                    data.Name = ss;
                    data.KeyName = equip.Name + "." + group.Name + "." + data.Name;
                    GetNodeAttributeValue(node, "remark", false, out ss);
                    data.Remark = ss;
                    GetNodeAttributeValue(node, "runname", false, out ss);
                    data.RunName = ss;
                    GetNodeAttributeValue(node, "datatype", false, out ss);
                    data.DataType = ss;
                    if (GetNodeAttributeValue(node, "max", false, out ss))
                    {
                        double d = 0;
                        if (double.TryParse(ss, out d))
                        {
                            data.Max = d.ToString();
                        }
                    }
                    if (GetNodeAttributeValue(node, "subtractor", false, out ss))
                    {
                        double d = 0;
                        if (double.TryParse(ss, out d))
                        {
                            data.Subtractor = d.ToString();
                        }
                    }
                    GetNodeAttributeValue(node, "start", true, out ss);
                    int dataStart = 0;
                    if (!int.TryParse(ss, out dataStart))
                    {
                        
                    }
                    data.Start = dataStart;

                    GetNodeAttributeValue(node, "len", true, out ss);
                    int dataLen = 1;
                    if (!int.TryParse(ss, out dataLen))
                    {
                        
                    }
                    data.Len = dataLen;
                    GetNodeAttributeValue(node, "method", false, out ss);
                    data.Method = ss;
                    GetNodeAttributeValue(node, "issave", false, out ss);
                    if (!string.IsNullOrWhiteSpace(ss))
                    {
                        data.IsSave = ss.ToLower().Trim() == "true";
                    }
                    if (group.Data.ContainsKey(data.Name))
                    {
                        
                    }
                    else
                    {
                        group.Data.Add(data.Name, data);
                    }
                }
                #endregion
            }
            #endregion

            Result.Add(equip.Name, equip);
        }

        public override bool Open()
        {
            throw new NotImplementedException();
        }

        public override bool Read(string block, int start, int len, out object[] buff)
        {
            throw new NotImplementedException();
        }

        public override bool Write(int block, int start, object[] buff)
        {
            throw new NotImplementedException();
        }

        public override void Close()
        {
            throw new NotImplementedException();
        }

        private bool GetNodeAttributeValue(XmlNode node, string attribute, bool throwException, out string value)
        {
            value = string.Empty;
            try
            {
                if (node.Attributes != null)
                {
                    XmlAttribute a = node.Attributes[attribute.ToLower()];
                    if (a != null && a.Value != null)
                    {
                        value = a.Value.ToString().Trim();
                    }
                }
                else
                {
                    return false;
                }
            }
            catch (Exception ex)
            {
                if (throwException)
                {
                    throw (ex);
                }
                return false;
            }
            return true;
        }
        private bool GetFirstNodeValue(XmlNode node, string path, string attribute, bool throwException, out string value)
        {
            value = string.Empty;
            try
            {
                XmlNode a = node.SelectSingleNode(path);
                if (a != null)
                {
                    GetNodeAttributeValue(a, attribute, throwException, out value);
                }
            }
            catch (Exception ex)
            {
                if (throwException)
                {
                    throw (ex);
                }
                return false;
            }
            return true;
        }

        
    }
}
